package com.sinog.biz.service.business.impl;

import com.sinog.biz.BizApplication;
import com.sinog.biz.mapper.havexml.other.SeeJieKouLogMapper;
import com.sinog.biz.service.business.FtpUtilService;
import com.sinog.biz.util.CodeUrlUtils;
import com.sinog.biz.util.FileUtil;
import com.sinog.biz.util.FtpUtil;
import com.sinog.biz.util.JdbcUtils;
import com.sinog.biz.util.enumstatus.UploadStatus;
import com.sinog.core.model.UploadAppendixFile;
import com.sinog.core.util.JsonUtil;
import com.sinog.core.util.StrUtil;
import com.sinog.core.utilbean.Constants;
import com.sinog.core.utilbean.Result;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.regex.Matcher;

/**
 * @desc ftp服务实现类
 * @author wangxj
 * @date 2021/12/6 15:45
 */
@Slf4j
@Service
public class FtpUtilServiceImpl implements FtpUtilService {

    @Value("${gkzx.azbj.ftp.datapath}")
    private String datapath;

    @Value("${gkzx.azbj.ftp.datapathsfb}")
    private String dataSfbPath;

    @Autowired
    private JdbcTemplate bujiJdbcTemplate;

    @Autowired
    private SeeJieKouLogMapper seeJieKouLogMapper;

    /**
     * 获取ftp详细信息
     * @return ip,port,username,passwd
     */
    @Override
    public Map<String,String> getFtpClient() {
        return FtpUtil.getFtpClientDetails();
    }

    /**
     * 描述
     * @param uploadAppendixFile uploadAppendixFile
     * @param type type
     * @return int
     */
    @Override
    public int fileIsExistence(UploadAppendixFile uploadAppendixFile,String type) {
        return FtpUtil.uploadFile(uploadAppendixFile,type);
    }

    /**
     * 从ftp下载文件到本地
     * @param realPath realPath
     * @param filepath filepath
     */
    @Override
    public void downLoadFromFtp(String realPath,String filepath) {
        FTPClient ftp;
        String[] fileUrlArr = StrUtil.getReplaceEnd(realPath);
        ftp = FtpUtil.getFtpClient();
        if(fileUrlArr.length > Constants.Number.NUM_TWO) {
            FtpUtil.downloadFile(ftp,datapath + fileUrlArr[fileUrlArr.length - 2],fileUrlArr[fileUrlArr.length - 1],filepath + fileUrlArr[fileUrlArr.length - 2]);
        }
    }

    /**
     * 描述
     * @param datapath datapath
     * @param filePath filePath
     */
    @Override
    public void uploadFileToFtp(String datapath,String filePath) {
        FTPClient ftp = null;
        try {
            ftp = FtpUtil.getFtpClient();
            FtpUtil.uploadFile(ftp,datapath,filePath);
        } finally {
            FtpUtil.closeFtpClient(ftp);
        }
    }

    /**
     * 描述
     * @param uploadAppendixFile uploadAppendixFile
     * @param path path
     * @param sfbdatapath sfbdatapath
     */
    @Override
    public void downLoadFromFtp3(UploadAppendixFile uploadAppendixFile,String path,String sfbdatapath) {
        try {
            FileUtil.downloadFile(getResponse(),getRequest(),uploadAppendixFile,path,sfbdatapath);
        } catch(IOException e) {
            log.error("文件下载发生异常:{}",e.getMessage());
        }
    }

    /**
     * 描述
     * @param s s
     * @param fileUrl fileUrl
     */
    @Override
    public void downLoadFromFtp5(String s,String fileUrl) {
        try {
            FileUtil.downloadFile(getRequest(),getResponse(),s,fileUrl);
        } catch(Exception e) {
            log.error(e.getMessage());
        }
    }

    /**
     * 描述
     * @param fileJson fileJson
     * @param path path
     * @param datapath datapath
     * @return String
     */
    @Override
    public String downLoadFromFtp6(String fileJson,String path,String datapath) {
        try {
            List<UploadAppendixFile> uploadAppendixFiles = JsonUtil.toList(fileJson,UploadAppendixFile.class);
            return FileUtil.downloadAppendixAllFile(getResponse(),getRequest(),uploadAppendixFiles,path,datapath);
        } catch(Exception e) {
            log.error(e.getMessage());
        }
        return null;
    }

    /**
     * 描述
     * @param path path
     * @param realPath realPath
     * @param pathTemp pathTemp
     * @return File
     */
    @Override
    public File uploadFileToFtp7(String path,String realPath,String pathTemp) {
        FTPClient ftp = null;
        File file = null;
        try {
            String[] fileUrlArr = realPath.split(Matcher.quoteReplacement(File.separator));
            String localDirPath = realPath.substring(0,realPath.lastIndexOf(File.separator));
            String ftppath = datapath + path;
            ftp = FtpUtil.getFtpClient();
            ftp.enterLocalPassiveMode();
            FTPFile[] ftpFiles = ftp.listFiles(ftppath);
            boolean ftpExist = FtpUtil.isFileExist(fileUrlArr[fileUrlArr.length - 1],ftpFiles);
            if(ftpExist) {
                boolean copyFileFlag = FtpUtil.downloadFile(ftp,ftppath,fileUrlArr[fileUrlArr.length - 1],localDirPath);
                if(copyFileFlag) {
                    file = new File(realPath);
                } else {
                    return null;
                }
            } else {
                return null;
            }
        } catch(Exception e) {
            log.info("发生异常:{}",e.getMessage());
        } finally {
            FtpUtil.closeFtpClient(ftp);
        }
        return file;
    }

    /**
     * 浏览所有培训文件的列表
     * @param flag 状态标识 0：上架 1：下架
     * @return String
     */
    @Override
    public String selectAllVideos(String flag) {
        //数据库操作
        ApplicationContext applicationContext = BizApplication.applicationContext;
        if(!ObjectUtils.allNotNull(bujiJdbcTemplate)) {
            bujiJdbcTemplate = (JdbcTemplate)applicationContext.getBean("bujiJdbcTemplate");
        }
        String sqlVideo = JdbcUtils.findMiddleVideosSql(flag);
        List<Map<String,Object>> maps = bujiJdbcTemplate.queryForList(sqlVideo);
        return JsonUtil.toText(maps);
    }

    /**
     * 更新文件上架状态
     * @param name 文件名
     * @param status 状态标识 0：上架 1：下架
     * @return Result
     */
    @Override
    public Result updateVideo(String name,String status){
        ApplicationContext applicationContext = BizApplication.applicationContext;
        if(!ObjectUtils.allNotNull(bujiJdbcTemplate)) {
            bujiJdbcTemplate = (JdbcTemplate)applicationContext.getBean("bujiJdbcTemplate");
        }
        String codeName = seeJieKouLogMapper.selectCodeNameByPrefix(CodeUrlUtils.getLocalCode());
        String sqlVideo = JdbcUtils.updateVideosSql(name,status,codeName);
        int update = bujiJdbcTemplate.update(sqlVideo);
        if(update>0){
            log.info("文件状态更新成功");
            return Result.success("文件状态更新成功");
        }else {
            log.info("文件状态更新失败");
            return Result.failure("文件状态更新失败");
        }
    }

    /**
     * 上传文件到司法部 ftp服务器中
     @param originalFilename 原文件名称
     @param originalFilePath 本地服务器上文件全路径
     @return Result
     */
    @Override
    public Result uploadFileToFtpRemote(String originalFilename,String originalFilePath,String desc) {
        log.info("培训资料远程上传文件开始。。。。。");
        FTPClient ftpClient = null;
        try {
            ftpClient = FtpUtil.getFtpClient();
            String suffixType = originalFilename.substring(originalFilename.lastIndexOf(".")+1);
            String remoteFilePath= this.dataSfbPath+ UUID.randomUUID() +"."+suffixType;
            //数据库操作
            ApplicationContext applicationContext = BizApplication.applicationContext;
            if(!ObjectUtils.allNotNull(bujiJdbcTemplate)) {
                log.info("培训资料远程中间库jdbc成功连接。。。。。");
                bujiJdbcTemplate = (JdbcTemplate)applicationContext.getBean("bujiJdbcTemplate");
            }
            String codeName = seeJieKouLogMapper.selectCodeNameByPrefix(CodeUrlUtils.getLocalCode());
            String sqlVideo = JdbcUtils.insertMiddleVideoSql(originalFilename,suffixType,desc,originalFilePath,remoteFilePath,codeName,codeName);
            try{
                int update = bujiJdbcTemplate.update(sqlVideo);
                if(update>0){
                    //上传文件
                    UploadStatus uploadStatus = FtpUtil.uploadRemoteFile(ftpClient,originalFilePath,remoteFilePath);
                    String message = uploadStatus.getName();
                    if(UploadStatus.Upload_New_File_Success.getName().equals(message)){
                        return  Result.success("远程文件上传司法部ftp成功");
                    }
                }
            }catch(DataAccessException e){
                log.error("中间库执行记录文件上传sql失败:{}",e.getMessage());
                return Result.failure("远程文件上传司法部ftp失败");
            }
        } catch(IOException e) {
            throw new RuntimeException(e);
        } finally {
            FtpUtil.closeFtpClient(ftpClient);
        }
        return  Result.success("远程文件上传司法部ftp成功");
    }

    /**
     * 删除文件以及远程文件
     * @param uploadFilePathName 本地上传文件全路径
     * @param originalFilename 文件名称
     * @return Result
     */
    @Override
    public Result delete(String uploadFilePathName,String originalFilename ) {
        String sqlLocal = JdbcUtils.selectLocalSqlByName(uploadFilePathName);
        try{
            //数据库操作
            ApplicationContext applicationContext = BizApplication.applicationContext;
            if(!ObjectUtils.allNotNull(bujiJdbcTemplate)) {
                bujiJdbcTemplate = (JdbcTemplate)applicationContext.getBean("bujiJdbcTemplate");
            }
            Integer localRest = bujiJdbcTemplate.queryForObject(sqlLocal,Integer.class);
            if(localRest!=null){
                //删除掉本地的
                Result result = FtpUtil.deleteLocal(uploadFilePathName);
                if(result.getCode()==1){
                    String ftpPath=null;
                    try{
                        String sqlFtp = JdbcUtils.selectMiddleVideoSqlByName(originalFilename);
                        ftpPath = bujiJdbcTemplate.queryForObject(sqlFtp,String.class);
                    }catch(DataAccessException dataAccessException){
                        log.info("-----------");
                    }
                    if(StringUtils.isNotBlank(ftpPath)){
                        FTPClient ftpClient = null;
                        try{
                            ftpClient=FtpUtil.getFtpClient();
                            String ftpName = ftpPath.substring(ftpPath.lastIndexOf("/")+1);
                            boolean ftpResult = FtpUtil.deleteFile(ftpClient,this.dataSfbPath,ftpName);
                            if(ftpResult){
                                String deleteByName = JdbcUtils.updateMiddleVideoSqlByName(originalFilename);
                                int update = bujiJdbcTemplate.update(deleteByName);
                                if(update>0){
                                    log.info("司法部数据文件删除成功");
                                }else{
                                    log.info("司法部数据文件删除失败");
                                    return Result.failure("远程文件上传司法部ftp失败--司法部数据文件删除失败");
                                }
                            }else{
                                log.info("{}:本地删除文件失败",originalFilename);
                                return Result.failure("远程文件上传司法部ftp失败--本地删除文件失败");
                            }
                        }finally {
                            FtpUtil.closeFtpClient(ftpClient);
                        }
                    }else{
                        return Result.failure("远程文件上传司法部ftp失败--远程删除文件");
                    }
                }

            }
        }catch(DataAccessException dataAccessException){
            log.info("-------------");
        }
        return Result.failure("没有此文件");
    }

    /**
     * 文件从ftp下载
     * @param fileName 真实文件名称
     * @param realPath 文件全路径
     */
    @Override
    public void downLoadVideoFromFtp(String fileName,String realPath) {
        //数据库操作
        ApplicationContext applicationContext = BizApplication.applicationContext;
        if(!ObjectUtils.allNotNull(bujiJdbcTemplate)) {
            bujiJdbcTemplate = (JdbcTemplate)applicationContext.getBean("bujiJdbcTemplate");
        }
        String ftpPath=null;
        try{
            String sqlFtp = JdbcUtils.selectMiddleVideoSqlByName(fileName);
            ftpPath = bujiJdbcTemplate.queryForObject(sqlFtp,String.class);
        }catch(DataAccessException dataAccessException){
            log.info("-----------");
        }
        if(ftpPath!=null){
                FTPClient ftpClient=FtpUtil.getFtpClient();
                String ftpName = ftpPath.substring(ftpPath.lastIndexOf("/")+1);
                //转移到FTP服务器目录
                try {
                    ftpClient.changeWorkingDirectory(this.dataSfbPath);
                    FTPFile[] fs = ftpClient.listFiles();
                    for (FTPFile ff : fs) {
                        if (ff.getName().equals(ftpName)) {
                            File localFile = new File(realPath);
                            OutputStream is = new FileOutputStream(localFile);
                            ftpClient.retrieveFile(ff.getName(), is);
                            is.close();
                        }
                    }
                } catch(IOException e) {
                    throw new RuntimeException(e);
                }finally {
                    FtpUtil.closeFtpClient(ftpClient);
                }
        }else{
            log.info("ftp文件下载到本地失败！");
        }
    }

    /**
     * 获取request
     * @return HttpServletRequest
     */
    private static HttpServletRequest getRequest() {
        return getRequestAttributes().getRequest();
    }

    /**
     * 获取response
     * @return HttpServletResponse
     */
    private static HttpServletResponse getResponse() {
        return getRequestAttributes().getResponse();
    }

    /**
     * 描述
     * @return ServletRequestAttributes
     */
    private static ServletRequestAttributes getRequestAttributes() {
        RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
        return (ServletRequestAttributes)attributes;
    }
}